package com.atguigu.schedule.controller;

import com.atguigu.schedule.common.Result;
import com.atguigu.schedule.mapper.SlamMapMapper;
import com.atguigu.schedule.mapper.SlamSessionMapper;
import com.atguigu.schedule.pojo.SlamMap;
import com.atguigu.schedule.pojo.SlamSession;
import com.atguigu.schedule.service.SlamService;
import com.atguigu.schedule.service.SlamProcessService;
import com.atguigu.schedule.service.RealSlamProcessingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.ResponseEntity;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * SLAM建图控制器
 * 提供SLAM建图相关的API接口
 */
@Slf4j
@RestController
@RequestMapping("/api/slam")
@RequiredArgsConstructor
public class SlamController {
    
    private final SlamService slamService;
    private final SlamMapMapper slamMapMapper;
    private final SlamSessionMapper slamSessionMapper;
    private final SlamProcessService slamProcessService;
    private final RealSlamProcessingService realSlamProcessingService;
    
    /**
     * 检查SLAM环境
     */
    @GetMapping("/environment/check")
    public Result<Map<String, Object>> checkEnvironment() {
        try {
            Map<String, Object> environment = slamService.checkSlamEnvironment();
            return Result.ok(environment);
        } catch (Exception e) {
            log.error("检查SLAM环境失败", e);
            return Result.build(null, 500, "检查环境失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建新的SLAM地图
     */
    @PostMapping("/maps")
    public Result<SlamMap> createMap(@RequestBody Map<String, Object> request) {
        try {
            String mapName = (String) request.get("mapName");
            String description = (String) request.get("description");
            
            if (mapName == null || mapName.trim().isEmpty()) {
                return Result.build(null, 400, "地图名称不能为空");
            }
            
            // 检查地图名称是否已存在
            if (slamMapMapper.selectByMapName(mapName) != null) {
                return Result.build(null, 400, "地图名称已存在");
            }
            
            SlamMap slamMap = SlamMap.builder()
                    .mapName(mapName)
                    .description(description)
                    .status(SlamMap.MapStatus.BUILDING)
                    .keyframeCount(0)
                    .mappointCount(0)
                    .createdAt(LocalDateTime.now())
                    .updatedAt(LocalDateTime.now())
                    .build();
            
            slamMapMapper.insert(slamMap);
            log.info("✅ 创建SLAM地图成功: {}", mapName);
            
            return Result.ok(slamMap);
            
        } catch (Exception e) {
            log.error("❌ 创建SLAM地图失败", e);
            return Result.build(null, 500, "创建地图失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取地图列表
     */
    @GetMapping("/maps")
    public Result<List<SlamMap>> getMaps(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String status) {
        try {
            List<SlamMap> maps;
            
            if (status != null && !status.trim().isEmpty()) {
                try {
                    SlamMap.MapStatus mapStatus = SlamMap.MapStatus.valueOf(status.toUpperCase());
                    maps = slamMapMapper.selectByStatus(mapStatus);
                } catch (IllegalArgumentException e) {
                    return Result.build(null, 400, "无效的状态参数");
                }
            } else {
                maps = slamMapMapper.selectAll();
            }
            
            return Result.ok(maps);
            
        } catch (Exception e) {
            log.error("获取地图列表失败", e);
            return Result.build(null, 500, "获取地图列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取地图详情
     */
    @GetMapping("/maps/{id}")
    public Result<SlamMap> getMap(@PathVariable Long id) {
        try {
            SlamMap map = slamMapMapper.selectById(id);
            if (map != null) {
                return Result.ok(map);
            } else {
                return Result.build(null, 404, "地图不存在");
            }
        } catch (Exception e) {
            log.error("获取地图详情失败", e);
            return Result.build(null, 500, "获取地图详情失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除地图
     */
    @DeleteMapping("/maps/{id}")
    public Result<Map<String, Object>> deleteMap(@PathVariable Long id) {
        try {
            SlamMap map = slamMapMapper.selectById(id);
            if (map == null) {
                return Result.build(null, 404, "地图不存在");
            }
            
            // 检查是否有活跃的会话
            List<SlamSession> activeSessions = slamSessionMapper.selectByMapId(id);
            boolean hasActiveSession = activeSessions.stream()
                    .anyMatch(session -> session.getStatus() == SlamSession.SessionStatus.RUNNING ||
                                       session.getStatus() == SlamSession.SessionStatus.STARTING ||
                                       session.getStatus() == SlamSession.SessionStatus.PAUSED);
            
            if (hasActiveSession) {
                return Result.build(null, 400, "地图正在使用中，无法删除");
            }
            
            slamMapMapper.deleteById(id);
            
            Map<String, Object> result = new HashMap<>();
            result.put("message", "地图删除成功");
            result.put("deletedId", id);
            
            log.info("✅ 删除SLAM地图成功: {}", id);
            return Result.ok(result);
            
        } catch (Exception e) {
            log.error("❌ 删除SLAM地图失败", e);
            return Result.build(null, 500, "删除地图失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建SLAM建图会话
     */
    @PostMapping("/sessions")
    public Result<SlamSession> createSession(@RequestBody Map<String, Object> request) {
        try {
            String sessionName = (String) request.get("sessionName");
            Long mapId = Long.valueOf(request.get("mapId").toString());
            String videoSource = (String) request.get("videoSource");
            
            if (sessionName == null || sessionName.trim().isEmpty()) {
                return Result.build(null, 400, "会话名称不能为空");
            }
            
            if (videoSource == null || videoSource.trim().isEmpty()) {
                return Result.build(null, 400, "视频源不能为空");
            }
            
            // 检查地图是否存在
            SlamMap map = slamMapMapper.selectById(mapId);
            if (map == null) {
                return Result.build(null, 404, "地图不存在");
            }
            
            // 检查会话名称是否已存在
            if (slamSessionMapper.selectBySessionName(sessionName) != null) {
                return Result.build(null, 400, "会话名称已存在");
            }
            
            SlamSession session = SlamSession.builder()
                    .sessionName(sessionName)
                    .mapId(mapId)
                    .status(SlamSession.SessionStatus.STARTING)
                    .videoSource(videoSource)
                    .cameraParams("/opt/smart-care-car/slam/ORB_SLAM2/test.yaml")
                    .vocabularyPath("/opt/smart-care-car/slam/ORB_SLAM2/Vocabulary/ORBvoc.txt")
                    .currentFrame(0)
                    .totalFrames(0)
                    .progressPercentage(0.0)
                    .build();
            
            slamSessionMapper.insert(session);
            log.info("✅ 创建SLAM会话成功: {}", sessionName);
            
            return Result.ok(session);
            
        } catch (Exception e) {
            log.error("❌ 创建SLAM会话失败", e);
            return Result.build(null, 500, "创建会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 启动SLAM建图会话
     */
    @PostMapping("/sessions/{id}/start")
    public Result<Map<String, Object>> startSession(@PathVariable Long id) {
        try {
            SlamSession sessionOpt = slamSessionMapper.selectById(id);
            if (sessionOpt == null) {
                return Result.build(null, 404, "会话不存在");
            }
            
                SlamSession session = sessionOpt;
            
            // 异步启动SLAM会话
            slamService.startSlamSession(session).thenAccept(updatedSession -> {
                slamSessionMapper.update(updatedSession);
            });
            
            Map<String, Object> result = new HashMap<>();
            result.put("message", "SLAM建图会话启动中");
            result.put("sessionId", id);
            result.put("status", "STARTING");
            
            log.info("🚀 启动SLAM建图会话: {}", session.getSessionName());
            return Result.ok(result);
            
        } catch (Exception e) {
            log.error("❌ 启动SLAM会话失败", e);
            return Result.build(null, 500, "启动会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 停止SLAM建图会话
     */
    @PostMapping("/sessions/{id}/stop")
    public Result<Map<String, Object>> stopSession(@PathVariable Long id) {
        try {
            SlamSession sessionOpt = slamSessionMapper.selectById(id);
            if (sessionOpt == null) {
                return Result.build(null, 404, "会话不存在");
            }
            
                SlamSession session = sessionOpt;
            
            // 异步停止SLAM会话
            slamService.stopSlamSession(id).thenAccept(success -> {
                if (success) {
                    session.setStatus(SlamSession.SessionStatus.STOPPED);
                    session.setEndedAt(LocalDateTime.now());
                    slamSessionMapper.update(session);
                }
            });
            
            Map<String, Object> result = new HashMap<>();
            result.put("message", "SLAM建图会话停止中");
            result.put("sessionId", id);
            result.put("status", "STOPPING");
            
            log.info("🛑 停止SLAM建图会话: {}", session.getSessionName());
            return Result.ok(result);
            
        } catch (Exception e) {
            log.error("❌ 停止SLAM会话失败", e);
            return Result.build(null, 500, "停止会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 暂停SLAM建图会话
     */
    @PostMapping("/sessions/{id}/pause")
    public Result<Map<String, Object>> pauseSession(@PathVariable Long id) {
        try {
            SlamSession sessionOpt = slamSessionMapper.selectById(id);
            if (sessionOpt == null) {
                return Result.build(null, 404, "会话不存在");
            }
            
                SlamSession session = sessionOpt;
            
            // 异步暂停SLAM会话
            slamService.pauseSlamSession(id).thenAccept(success -> {
                if (success) {
                    session.setStatus(SlamSession.SessionStatus.PAUSED);
                    slamSessionMapper.update(session);
                }
            });
            
            Map<String, Object> result = new HashMap<>();
            result.put("message", "SLAM建图会话暂停中");
            result.put("sessionId", id);
            result.put("status", "PAUSING");
            
            log.info("⏸️ 暂停SLAM建图会话: {}", session.getSessionName());
            return Result.ok(result);
            
        } catch (Exception e) {
            log.error("❌ 暂停SLAM会话失败", e);
            return Result.build(null, 500, "暂停会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 恢复SLAM建图会话
     */
    @PostMapping("/sessions/{id}/resume")
    public Result<Map<String, Object>> resumeSession(@PathVariable Long id) {
        try {
            SlamSession sessionOpt = slamSessionMapper.selectById(id);
            if (sessionOpt == null) {
                return Result.build(null, 404, "会话不存在");
            }
            
                SlamSession session = sessionOpt;
            
            // 异步恢复SLAM会话
            slamService.resumeSlamSession(id).thenAccept(success -> {
                if (success) {
                    session.setStatus(SlamSession.SessionStatus.RUNNING);
                    slamSessionMapper.update(session);
                }
            });
            
            Map<String, Object> result = new HashMap<>();
            result.put("message", "SLAM建图会话恢复中");
            result.put("sessionId", id);
            result.put("status", "RESUMING");
            
            log.info("▶️ 恢复SLAM建图会话: {}", session.getSessionName());
            return Result.ok(result);
            
        } catch (Exception e) {
            log.error("❌ 恢复SLAM会话失败", e);
            return Result.build(null, 500, "恢复会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取会话状态
     */
    @GetMapping("/sessions/{id}/status")
    public Result<Map<String, Object>> getSessionStatus(@PathVariable Long id) {
        try {
            SlamSession sessionOpt = slamSessionMapper.selectById(id);
            if (sessionOpt == null) {
                return Result.build(null, 404, "会话不存在");
            }
            
                SlamSession session = sessionOpt;
            SlamSession.SessionStatus currentStatus = slamService.getSessionStatus(id);
            
            Map<String, Object> result = new HashMap<>();
            result.put("sessionId", id);
            result.put("status", currentStatus);
            result.put("currentFrame", session.getCurrentFrame());
            result.put("totalFrames", session.getTotalFrames());
            result.put("progressPercentage", session.getProgressPercentage());
            result.put("errorMessage", session.getErrorMessage());
            
            return Result.ok(result);
            
        } catch (Exception e) {
            log.error("获取会话状态失败", e);
            return Result.build(null, 500, "获取会话状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取实时轨迹数据
     */
    @GetMapping("/sessions/{id}/trajectory")
    public Result<List<Map<String, Object>>> getRealtimeTrajectory(@PathVariable Long id) {
        try {
            List<Map<String, Object>> trajectory = slamService.getRealtimeTrajectory(id);
            return Result.ok(trajectory);
        } catch (Exception e) {
            log.error("获取实时轨迹失败", e);
            return Result.build(null, 500, "获取实时轨迹失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取会话列表
     */
    @GetMapping("/sessions")
    public Result<List<SlamSession>> getSessions(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String status) {
        try {
            // 分页参数暂未使用，MyBatis需要手动实现分页
            List<SlamSession> sessions;
            
            if (status != null && !status.trim().isEmpty()) {
                try {
                    SlamSession.SessionStatus sessionStatus = SlamSession.SessionStatus.valueOf(status.toUpperCase());
                    sessions = slamSessionMapper.selectByStatus(sessionStatus);
                } catch (IllegalArgumentException e) {
                    return Result.build(null, 400, "无效的状态参数");
                }
            } else {
                sessions = slamSessionMapper.selectAll();
            }
            
            return Result.ok(sessions);
            
        } catch (Exception e) {
            log.error("获取会话列表失败", e);
            return Result.build(null, 500, "获取会话列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取全局SLAM状态
     * @return SLAM状态信息
     */
    @GetMapping("/status")
    public Result<Map<String, Object>> getGlobalSlamStatus() {
        try {
            Map<String, Object> status = new HashMap<>();
            
            // 获取当前活跃的会话数量
            List<SlamSession> activeSessions = slamSessionMapper.selectByStatus(
                SlamSession.SessionStatus.RUNNING
            );
            
            // 计算全局统计信息
            int totalKeyframes = 0;
            int totalMapPoints = 0;
            double totalTrajectoryLength = 0.0;
            double averageProgress = 0.0;
            
            // 尝试从SLAM输出文件读取真实数据
            try {
                log.info("🔍 开始读取SLAM数据文件...");
                ProcessBuilder pb = new ProcessBuilder("python3", "/opt/smart-care-car/slam/read_slam_data.py", "/opt/smart-care-car/slam/output");
                pb.redirectErrorStream(true);
                Process process = pb.start();
                
                // 等待进程完成，最多等待10秒
                boolean finished = process.waitFor(10, java.util.concurrent.TimeUnit.SECONDS);
                if (!finished) {
                    log.warn("⚠️ Python脚本执行超时，强制终止");
                    process.destroyForcibly();
                }
                
                int exitCode = process.exitValue();
                log.info("📊 Python脚本执行完成，退出码: {}", exitCode);
                
                if (exitCode == 0) {
                    // 读取Python脚本输出
                    java.util.Scanner scanner = new java.util.Scanner(process.getInputStream());
                    StringBuilder jsonOutput = new StringBuilder();
                    while (scanner.hasNextLine()) {
                        String line = scanner.nextLine();
                        jsonOutput.append(line);
                        log.debug("Python输出: {}", line);
                    }
                    scanner.close();
                    
                    String jsonString = jsonOutput.toString().trim();
                    log.info("📄 Python脚本输出: {}", jsonString);
                    
                    if (!jsonString.isEmpty()) {
                        // 解析JSON数据
                        com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
                        com.fasterxml.jackson.databind.JsonNode jsonNode = mapper.readTree(jsonString);
                        
                        totalKeyframes = jsonNode.get("keyframes").asInt();
                        totalMapPoints = jsonNode.get("mapPoints").asInt();
                        totalTrajectoryLength = jsonNode.get("trajectoryLength").asDouble();
                        averageProgress = jsonNode.get("progress").asDouble();
                        
                        log.info("✅ 从SLAM输出文件读取到真实数据: 关键帧={}, 地图点={}, 轨迹长度={}, 进度={}%", 
                            totalKeyframes, totalMapPoints, totalTrajectoryLength, averageProgress);
                    } else {
                        log.warn("⚠️ Python脚本输出为空");
                        throw new RuntimeException("Python脚本输出为空");
                    }
                } else {
                    log.warn("⚠️ Python脚本执行失败，退出码: {}", exitCode);
                    throw new RuntimeException("Python脚本执行失败，退出码: " + exitCode);
                }
            } catch (Exception e) {
                log.error("❌ 读取SLAM数据失败: {}", e.getMessage(), e);
                // 使用数据库数据作为备选
                for (SlamSession session : activeSessions) {
                    int currentFrame = session.getCurrentFrame() != null ? session.getCurrentFrame() : 0;
                    double progress = session.getProgressPercentage() != null ? session.getProgressPercentage() : 0.0;
                    
                    totalKeyframes += currentFrame;
                    totalMapPoints += currentFrame * 10;
                    totalTrajectoryLength += currentFrame * 0.1;
                    averageProgress += progress;
                }
            }
            
            if (!activeSessions.isEmpty()) {
                averageProgress /= activeSessions.size();
            }
            
            status.put("activeSessions", activeSessions.size());
            status.put("keyframes", totalKeyframes);
            status.put("mapPoints", totalMapPoints);
            status.put("trajectoryLength", Math.round(totalTrajectoryLength * 100.0) / 100.0);
            status.put("progress", Math.round(averageProgress * 10.0) / 10.0);
            status.put("timestamp", LocalDateTime.now());
            
            return Result.build(status, 200, "获取SLAM状态成功");
            
        } catch (Exception e) {
            log.error("获取SLAM状态失败", e);
            return Result.error("获取SLAM状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 启动全局SLAM处理
     * @param request 启动请求
     * @return 启动结果
     */
    @PostMapping("/start")
    public Result<Map<String, Object>> startGlobalSlam(@RequestBody Map<String, Object> request) {
        try {
            String streamUrl = (String) request.get("streamUrl");
            String sessionId = (String) request.get("sessionId");
            String mode = (String) request.get("mode");
            
            log.info("启动全局SLAM处理: streamUrl={}, sessionId={}, mode={}", streamUrl, sessionId, mode);
            
            // 创建新的SLAM会话
            SlamSession session = new SlamSession();
            session.setSessionName("Global SLAM Session");
            session.setStatus(SlamSession.SessionStatus.RUNNING);
            
            slamSessionMapper.insert(session);
            
            // 根据模式启动SLAM处理
            boolean processStarted = false;
            String videoSource = "/opt/smart-care-car/slam/ORB_SLAM2/test.mp4"; // 默认视频源
            
            if ("webrtc".equals(mode)) {
                // WebRTC模式：启动真实WebRTC SLAM处理器
                log.info("WebRTC模式：启动真实WebRTC SLAM处理器");
                try {
                    ProcessBuilder pb = new ProcessBuilder(
                        "python3", 
                        "/opt/smart-care-car/slam/real_webrtc_slam_processor.py", 
                        session.getId().toString(), 
                        "/opt/smart-care-car/slam/output"
                    );
                    pb.redirectErrorStream(true);
                    
                    Process process = pb.start();
                    Thread.sleep(1000); // 等待进程启动
                    
                    if (process.isAlive()) {
                        processStarted = true;
                        log.info("✅ WebRTC SLAM处理器启动成功，会话ID: {}, 进程ID: {}", session.getId(), process.pid());
                    } else {
                        log.error("❌ WebRTC SLAM处理器启动失败");
                    }
                } catch (Exception e) {
                    log.error("❌ 启动WebRTC SLAM处理器失败: {}", e.getMessage(), e);
                }
            } else {
                // 默认模式：启动SLAM进程
                log.info("默认模式：启动SLAM进程");
                processStarted = slamProcessService.startSlamProcess(session.getId(), videoSource);
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("sessionId", session.getId());
            result.put("status", "started");
            result.put("mode", mode != null ? mode : "default");
            result.put("message", "SLAM处理已启动");
            
            return Result.build(result, 200, "启动SLAM成功");
            
        } catch (Exception e) {
            log.error("启动SLAM失败", e);
            return Result.error("启动SLAM失败: " + e.getMessage());
        }
    }
    
    /**
     * 停止全局SLAM处理
     * @return 停止结果
     */
    @PostMapping("/stop")
    public Result<Map<String, Object>> stopGlobalSlam() {
        try {
            log.info("停止全局SLAM处理");
            
            // 停止所有运行中的SLAM进程
            Map<Long, SlamProcessService.SlamProcessData> allProcessData = slamProcessService.getAllProcessData();
            int stoppedCount = 0;
            
            for (Long sessionId : allProcessData.keySet()) {
                if (slamProcessService.stopSlamProcess(sessionId)) {
                    stoppedCount++;
                }
            }
            
            // 停止所有活跃的会话
            List<SlamSession> activeSessions = slamSessionMapper.selectByStatus(
                SlamSession.SessionStatus.RUNNING
            );
            
            for (SlamSession session : activeSessions) {
                slamService.stopSlamSession(session.getId());
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("stoppedProcesses", stoppedCount);
            result.put("stoppedSessions", activeSessions.size());
            result.put("status", "stopped");
            result.put("message", "SLAM处理已停止，共停止 " + stoppedCount + " 个进程");
            
            return Result.build(result, 200, "停止SLAM成功");
            
        } catch (Exception e) {
            log.error("停止SLAM失败", e);
            return Result.error("停止SLAM失败: " + e.getMessage());
        }
    }
    
    /**
     * 暂停全局SLAM处理
     * @return 暂停结果
     */
    @PostMapping("/pause")
    public Result<Map<String, Object>> pauseGlobalSlam() {
        try {
            log.info("暂停全局SLAM处理");
            
            // 暂停所有活跃的会话
            List<SlamSession> activeSessions = slamSessionMapper.selectByStatus(
                SlamSession.SessionStatus.RUNNING
            );
            
            for (SlamSession session : activeSessions) {
                slamService.pauseSlamSession(session.getId());
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("pausedSessions", activeSessions.size());
            result.put("status", "paused");
            result.put("message", "SLAM处理已暂停");
            
            return Result.build(result, 200, "暂停SLAM成功");
            
        } catch (Exception e) {
            log.error("暂停SLAM失败", e);
            return Result.error("暂停SLAM失败: " + e.getMessage());
        }
    }
    
    /**
     * 上传视频文件
     */
    @PostMapping("/upload/video")
    public Result<Map<String, Object>> uploadVideo(@RequestParam("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                return Result.build(null, 400, "视频文件不能为空");
            }
            
            // 检查文件类型
            String contentType = file.getContentType();
            if (contentType == null || !contentType.startsWith("video/")) {
                return Result.build(null, 400, "请上传视频文件");
            }
            
            // 创建上传目录
            Path uploadDir = Paths.get("/opt/smart-care-car/slam/uploads");
            Files.createDirectories(uploadDir);
            
            // 生成唯一文件名
            String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
            Path filePath = uploadDir.resolve(fileName);
            
            // 保存文件
            Files.copy(file.getInputStream(), filePath);
            
            Map<String, Object> result = new HashMap<>();
            result.put("fileName", fileName);
            result.put("filePath", filePath.toString());
            result.put("fileSize", file.getSize());
            result.put("contentType", contentType);
            
            log.info("✅ 视频文件上传成功: {}", fileName);
            return Result.ok(result);
            
        } catch (IOException e) {
            log.error("❌ 视频文件上传失败", e);
            return Result.build(null, 500, "文件上传失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取SLAM统计信息
     */
    @GetMapping("/statistics")
    public Result<Map<String, Object>> getStatistics() {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            // 地图统计
            long totalMaps = slamMapMapper.selectAll().size();
            List<Object[]> mapStatusCounts = slamMapMapper.countByStatus();
            Map<String, Long> mapStats = new HashMap<>();
            for (Object[] count : mapStatusCounts) {
                mapStats.put(count[0].toString(), (Long) count[1]);
            }
            
            // 会话统计
            long totalSessions = slamSessionMapper.selectAll().size();
            List<Object[]> sessionStatusCounts = slamSessionMapper.countByStatus();
            Map<String, Long> sessionStats = new HashMap<>();
            for (Object[] count : sessionStatusCounts) {
                sessionStats.put(count[0].toString(), (Long) count[1]);
            }
            
            // 活跃会话
            List<SlamSession> activeSessions = slamSessionMapper.selectActiveSessions();
            
            stats.put("totalMaps", totalMaps);
            stats.put("mapStatusCounts", mapStats);
            stats.put("totalSessions", totalSessions);
            stats.put("sessionStatusCounts", sessionStats);
            stats.put("activeSessions", activeSessions.size());
            stats.put("activeSessionIds", slamService.getActiveSessionIds());
            
            return Result.ok(stats);
            
        } catch (Exception e) {
            log.error("获取SLAM统计信息失败", e);
            return Result.build(null, 500, "获取统计信息失败: " + e.getMessage());
        }
    }
    
    @PostMapping("/webrtc/frame")
    public Result<Map<String, Object>> receiveWebRTCFrame(@RequestBody Map<String, Object> request) {
        try {
            String sessionId = (String) request.get("sessionId");
            String frameData = (String) request.get("frame");
            Long timestamp = ((Number) request.get("timestamp")).longValue();
            Integer width = ((Number) request.get("width")).intValue();
            Integer height = ((Number) request.get("height")).intValue();
            
            log.debug("📡 接收到WebRTC视频帧: 会话ID={}, 尺寸={}x{}, 时间戳={}", 
                sessionId, width, height, timestamp);
            
            // 这里可以将视频帧保存到文件或发送给SLAM处理器
            // 目前只是记录日志
            log.debug("📊 视频帧数据长度: {} bytes", frameData.length());
            
            Map<String, Object> responseData = Map.of(
                "sessionId", sessionId,
                "timestamp", timestamp,
                "processed", true
            );
            
            return Result.ok(responseData);
            
        } catch (Exception e) {
            log.error("❌ 接收WebRTC视频帧失败: {}", e.getMessage(), e);
            return Result.error("接收视频帧失败: " + e.getMessage());
        }
    }
    
    /**
     * 接收SLAM会话的视频帧数据
     * 用于前端发送视频帧到指定会话
     */
    @PostMapping("/sessions/{id}/frame")
    public Result<Map<String, Object>> receiveSessionFrame(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request) {
        try {
            String frameData = (String) request.get("frame");
            Long timestamp = System.currentTimeMillis();
            
            log.debug("📡 接收到SLAM会话视频帧: 会话ID={}, 时间戳={}", id, timestamp);
            log.debug("📊 视频帧数据长度: {} bytes", frameData != null ? frameData.length() : 0);
            
            // 这里可以将视频帧保存到文件或发送给SLAM处理器
            // 目前只是记录日志并返回成功响应
            
            Map<String, Object> responseData = Map.of(
                "sessionId", id,
                "timestamp", timestamp,
                "processed", true,
                "message", "帧数据接收成功"
            );
            
            return Result.ok(responseData);
            
        } catch (Exception e) {
            log.error("❌ 接收SLAM会话视频帧失败: {}", e.getMessage(), e);
            return Result.error("接收视频帧失败: " + e.getMessage());
        }
    }
    
    /**
     * 处理真实视频帧进行SLAM分析
     * 参考人脸识别功能的实现模式
     */
    @PostMapping("/process-frame")
    public Result<Map<String, Object>> processVideoFrame(
            @RequestParam("sessionId") Long sessionId,
            @RequestParam("image") MultipartFile image) {
        try {
            if (image.isEmpty()) {
                return Result.build(null, 400, "图像文件不能为空");
            }
            
            log.info("🎯 开始处理真实SLAM视频帧，会话ID: {}", sessionId);
            
            byte[] imageData = image.getBytes();
            return realSlamProcessingService.processVideoFrame(sessionId, imageData);
            
        } catch (Exception e) {
            log.error("❌ 处理真实SLAM视频帧失败", e);
            return Result.build(null, 500, "处理视频帧失败: " + e.getMessage());
        }
    }
    
    /**
     * 启动真实SLAM会话
     */
    @PostMapping("/real/start")
    public Result<String> startRealSlamSession(@RequestBody Map<String, Object> request) {
        try {
            Long sessionId = Long.valueOf(request.get("sessionId").toString());
            String sessionName = request.get("sessionName").toString();
            
            log.info("🚀 启动真实SLAM会话: {}", sessionName);
            return realSlamProcessingService.startSlamSession(sessionId, sessionName);
            
        } catch (Exception e) {
            log.error("❌ 启动真实SLAM会话失败", e);
            return Result.build(null, 500, "启动SLAM会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 停止真实SLAM会话
     */
    @PostMapping("/real/stop")
    public Result<String> stopRealSlamSession(@RequestBody Map<String, Object> request) {
        try {
            Long sessionId = Long.valueOf(request.get("sessionId").toString());
            
            log.info("🛑 停止真实SLAM会话: {}", sessionId);
            return realSlamProcessingService.stopSlamSession(sessionId);
            
        } catch (Exception e) {
            log.error("❌ 停止真实SLAM会话失败", e);
            return Result.build(null, 500, "停止SLAM会话失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取真实SLAM状态
     */
    @GetMapping("/real/status/{sessionId}")
    public Result<Map<String, Object>> getRealSlamStatus(@PathVariable Long sessionId) {
        try {
            log.info("📊 获取真实SLAM状态，会话ID: {}", sessionId);
            return realSlamProcessingService.getSlamStatus(sessionId);
            
        } catch (Exception e) {
            log.error("❌ 获取真实SLAM状态失败", e);
            return Result.build(null, 500, "获取SLAM状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取SLAM实时数据
     */
    @GetMapping("/sessions/{sessionId}/realtime-data")
    public Result<Map<String, Object>> getRealtimeSlamData(@PathVariable Long sessionId) {
        try {
            log.info("📊 获取SLAM实时数据，会话ID: {}", sessionId);
            return slamService.getRealtimeSlamData(sessionId);
            
        } catch (Exception e) {
            log.error("❌ 获取SLAM实时数据失败", e);
            return Result.build(null, 500, "获取SLAM实时数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取SLAM轨迹数据
     */
    @GetMapping("/sessions/{sessionId}/trajectory")
    public Result<Map<String, Object>> getSlamTrajectory(@PathVariable Long sessionId) {
        try {
            log.info("🗺️ 获取SLAM轨迹数据，会话ID: {}", sessionId);
            return slamService.getSlamTrajectory(sessionId);
            
        } catch (Exception e) {
            log.error("❌ 获取SLAM轨迹数据失败", e);
            return Result.build(null, 500, "获取SLAM轨迹数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取SLAM关键帧数据
     */
    @GetMapping("/sessions/{sessionId}/keyframes")
    public Result<Map<String, Object>> getSlamKeyframes(@PathVariable Long sessionId) {
        try {
            log.info("🔑 获取SLAM关键帧数据，会话ID: {}", sessionId);
            return slamService.getSlamKeyframes(sessionId);
            
        } catch (Exception e) {
            log.error("❌ 获取SLAM关键帧数据失败", e);
            return Result.build(null, 500, "获取SLAM关键帧数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取SLAM地图点数据
     */
    @GetMapping("/sessions/{sessionId}/map-points")
    public Result<Map<String, Object>> getSlamMapPoints(@PathVariable Long sessionId) {
        try {
            log.info("🗺️ 获取SLAM地图点数据，会话ID: {}", sessionId);
            return slamService.getSlamMapPoints(sessionId);
            
        } catch (Exception e) {
            log.error("❌ 获取SLAM地图点数据失败", e);
            return Result.build(null, 500, "获取SLAM地图点数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 查看SLAM图片
     */
    @GetMapping("/view-images")
    public void viewImages(@RequestParam String type, 
                          @RequestParam Long sessionId,
                          HttpServletResponse response) {
        try {
            log.info("🖼️ 查看SLAM图片，类型: {}, 会话ID: {}", type, sessionId);
            slamService.viewImages(type, sessionId, response);
            
        } catch (Exception e) {
            log.error("❌ 查看SLAM图片失败", e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("查看图片失败: " + e.getMessage());
            } catch (IOException ioException) {
                log.error("❌ 写入错误响应失败", ioException);
            }
        }
    }
}
